#ifndef __ZHONG_CONNECTION__
#define __ZHONG_CONNECTION__
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
#include <iostream>
#include <unordered_map>
#include <functional>
#include <mutex>
#include <memory>
#include"logger.hpp"

namespace bite_im
{
    using server_t = websocketpp::server<websocketpp::config::asio>;
    // 长连接类型 server_t::connection_ptr

    class Connection
    {
    public:
        // 客户端对象代表登录的某一个特定用户
        struct Client
        {
            Client(const std::string &sid, const std::string &uid) : user_id(uid), session_id(sid) {}
            std::string user_id;    // 指定某个用户
            std::string session_id; // 用户是否登录--登录会话id
        };
        using ptr = std::shared_ptr<Connection>;

        Connection() {}
        ~Connection() {}

        // 用户登录时，添加一个长连接
        void insert(const server_t::connection_ptr &conn, const std::string &session_id, const std::string &user_id)
        {
            std::unique_lock<std::mutex> lock(_mutex); // 需要加锁
            // _user_connection[user_id] = conn;
            _user_connection.insert(std::make_pair(user_id, conn));
            // Client c(session_id, user_id);
            _connection_client.insert(std::make_pair(conn, Client(session_id, user_id))) ;
            LOG_INFO("新增一个长连接[{}]-[{}]-[{}]成功", (size_t)conn.get(), session_id, user_id);
        }
        // 通过用户id获取一个长连接
        server_t::connection_ptr connection(const std::string &user_id)
        {
            std::unique_lock<std::mutex> lock(_mutex); // 需要加锁
            auto it = _user_connection.find(user_id);
            if (it == _user_connection.end())
            {
                LOG_ERROR("未找到用户[{}]对应的长连接", user_id);
                return server_t::connection_ptr();
            }
            return it->second;
        }
        // 通过长链接获取用户信息
        bool client(const server_t::connection_ptr &conn, std::string &session_id, std::string &user_id)
        {
            std::unique_lock<std::mutex> lock(_mutex); // 需要加锁
            auto it = _connection_client.find(conn);
            if (it == _connection_client.end())
            {
                session_id = "";
                user_id = "";
                LOG_ERROR("未找到对应的长连接[{}]", (size_t)conn.get());
                return false;
            }
            session_id = it->second.session_id;
            user_id = it->second.user_id;
            return true;
        }
        // 用户退出时删除长连接
        bool remove(const server_t::connection_ptr &conn)
        {
            std::unique_lock<std::mutex> lock(_mutex); // 需要加锁
            auto it = _connection_client.find(conn);
            if (it == _connection_client.end())
            {
                LOG_ERROR("未找到对应的长连接[{}]", (size_t)conn.get());
                // 不存在这个长连接
                return false;
            }
            std::string user_id = it->second.user_id;
            _connection_client.erase(conn); // 删掉<长连接, 客户端> 映射
            
            auto it1 = _user_connection.find(user_id);
            if (it1 == _user_connection.end())
            {
                LOG_ERROR("未找到对应的长连接对应的用户信息[{}]", user_id);
                // 不存在这个用户
                return false;
            }
            _user_connection.erase(user_id); // 删掉<用户id, 长连接> 映射
            return true;
        }

    private:
        std::mutex _mutex;
        // <用户id, 长连接> 映射
        std::unordered_map<std::string, server_t::connection_ptr> _user_connection;
        // <长连接, 客户端> 映射
        std::unordered_map<server_t::connection_ptr, Client> _connection_client;
    };
}

#endif